-
Notifications
You must be signed in to change notification settings - Fork 44
Feat: add mithril-client
CLI command for UTxO-HD ledger state snapshot conversion
#2518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feat: add mithril-client
CLI command for UTxO-HD ledger state snapshot conversion
#2518
Conversation
…retrieve the `snapshot-converter` binary
/// Trait for interacting with the GitHub API to retrieve Cardano node release. | ||
#[cfg_attr(test, mockall::automock)] | ||
#[async_trait] | ||
pub trait GitHubApiClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you need a trait for a GitHub API Client, you should do the following:
- rename the module to
github_release_retriever.rs
- rename the trait to
GitHubReleaserRetriever
(and put it in aninterface.rs
sub-module?) - move the
GitHubRelease
in the module - rename the
reqwest_github_api_client.rs
sub-module toreqwest.rs
let url = Url::parse(&url) | ||
.with_context(|| format!("Failed to parse URL for GitHub API: {}", url))?; | ||
|
||
let response = self | ||
.client | ||
.get(url.clone()) | ||
.send() | ||
.await | ||
.with_context(|| format!("Failed to send request to GitHub API: {}", url))?; | ||
|
||
let response = response.text().await?; | ||
let release: GitHubRelease = serde_json::from_str(&response) | ||
.with_context(|| format!("Failed to parse response from GitHub API: {:?}", response))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code can be refactored in a function that retrieves the content from a URL and deserialize it into a generic type.
This download
function could even be part of the HttpDownloader
trait (by renaming the existing download
function to download_file
).
} | ||
|
||
impl GitHubRelease { | ||
pub fn is_prerelease(&self) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is probably interesting only if the visibility of the prerelease
field is not public.
fn dummy_linux_asset() -> GitHubAsset { | ||
GitHubAsset { | ||
name: format!("asset-name-{}.tar.gz", ASSET_PLATFORM_LINUX), | ||
browser_download_url: "https://release-assets.com/linux".to_string(), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you can have only one function fn dummy_asset(os: &str) -> GitHubAsset
here.
fs2 = "0.4.3" | ||
futures = "0.3.31" | ||
human_bytes = { version = "0.4.3", features = ["fast"] } | ||
indicatif = { version = "0.17.11", features = ["tokio"] } | ||
mithril-cli-helper = { path = "../internal/mithril-cli-helper" } | ||
mithril-client = { path = "../mithril-client", features = ["fs", "unstable"] } | ||
mithril-doc = { path = "../internal/mithril-doc" } | ||
reqwest = { workspace = true } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The workspace only specify the minimal set of shared features for reqwest since we don't want to force them on downstream library users.
For our binaries we needs a bit more:
reqwest = { workspace = true } | |
reqwest = { workspace = true, features = [ | |
"default", | |
"gzip", | |
"zstd", | |
"deflate", | |
"brotli" | |
] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should keep the commands module focused and move all utilities to the utils
module (archive unpacker, github api client, http downloader).
let root_file = temp_dir.join("root.txt"); | ||
assert!(root_file.exists()); | ||
let root_file_content = fs::read_to_string(root_file).unwrap(); | ||
assert_eq!(root_file_content, "root content"); | ||
|
||
let nested_file = temp_dir.join("nested/dir/nested-file.txt"); | ||
assert!(nested_file.exists()); | ||
let nested_file_content = fs::read_to_string(nested_file).unwrap(); | ||
assert_eq!(nested_file_content, "nested content"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: You could use assert_dir_eq
for the existence check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any value to return a ArchiveUnpacker
instance to this api users ? It seems to exist only to enable testing.
It would refactor a bit this part:
- Rename
ArchiveUnpacker
trait toArchiveFormat
with two methods: the actualunpack
method and asupport(&path) -> bool
method - Rename
ArchiveUnpackerSelector
toArchiveUnpacker
:- with two methods: a public
unpack(&path) -> Result<()>
method and a privateselect_unpacker
method - It would contains a list of
ArchiveFormat
impl and aDefault
impl that would manually add the two known format to this list. select_unpacker
would iterate over its format list and return the first unpacker whichsupport
the given archiveunpack
would simply callselect_unpacker
then do the unpacking.
- with two methods: a public
let root_file = temp_dir.join("root.txt"); | ||
assert!(root_file.exists()); | ||
let root_file_content = fs::read_to_string(&root_file).unwrap(); | ||
assert_eq!(root_file_content, "root content"); | ||
|
||
let nested_file = temp_dir.join("nested/dir/nested-file.txt"); | ||
assert!(nested_file.exists()); | ||
let nested_file_content = fs::read_to_string(&nested_file).unwrap(); | ||
assert_eq!(nested_file_content, "nested content"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: You could use assert_dir_eq for the existence check.
const LEDGER_DIR: &str = "ledger"; | ||
|
||
#[derive(Debug, Clone, ValueEnum)] | ||
enum UTxOHDFlavor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to support lower case (and maybe only lower case) here ?
/// Main command execution | ||
pub async fn execute(&self) -> MithrilResult<()> { | ||
let distribution_temp_dir = self.db_directory.join(CARDANO_DISTRIBUTION_TEMP_DIR); | ||
std::fs::create_dir(distribution_temp_dir.clone()).with_context(|| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most fs
methods takes AsRef<Path>
as input which accept both moving the provided value or passing it by reference.
std::fs::create_dir(distribution_temp_dir.clone()).with_context(|| { | |
std::fs::create_dir(&distribution_temp_dir).with_context(|| { |
Content
This PR includes...
Pre-submit checklist
Comments
Issue(s)
Closes #2492